﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using Microsoft.TeamFoundation.VersionControl.Client;

namespace TfsBranchLib2.Model
{
    public class TfsItem : TreeViewItem
    {
        private bool canBeChecked = true;

        private CheckBox checkBox;
        private bool isChecked;

        private ItemSet items;
        private VersionControlServer versionControlServer;


        private TfsItem working;
        public string ItemName { get; set; }
        public string FullPath { get; set; }

        public bool Checked
        {
            get { return isChecked; }
            set
            {
                isChecked = value;
                if (checkBox != null)
                {
                    checkBox.IsChecked = isChecked;
                }
            }
        }

        public bool CanBeChecked
        {
            get { return canBeChecked; }
            set
            {
                canBeChecked = value;
                if (checkBox != null)
                {
                    checkBox.IsEnabled = value;
                }
            }
        }

        //public ObservableCollection<TfsItem> SubItems { get; set; }
        protected bool IsFolder { get; set; }

        public void GetSubItems()
        {
            if (!IsFolder) return;

            if (Items[0] == null) return;

            if (Items[0] == working)
            {
                var thread = new Thread(m => { GetItemForPath(); });
                thread.SetApartmentState(ApartmentState.STA);
                thread.Start(FullPath);
            }
        }

        private void UpdateItemsForNode()
        {
            foreach (var item in items.Items)
            {
                if (item.ServerItem != FullPath)
                {
                    // If current not canBeChecked but the node is not checked (if checked then sub items can't be checked)
                    var tfsItem = CreateTfsItem(versionControlServer, item, canBeChecked && (!Checked));
                    Trace.WriteLine(item.ServerItem);
                    Items.Add(tfsItem);
                }
            }
            Items.Remove(working);
        }

        public void GetItemForPath()
        {
            items = versionControlServer.GetItems(FullPath, VersionSpec.Latest, RecursionType.OneLevel);
            Dispatcher.Invoke(UpdateItemsForNode);
        }

        public bool IsSubItems()
        {
            if (items == null)
            {
                return false;
            }
            return true;
        }


        protected override void OnExpanded(RoutedEventArgs e)
        {
            base.OnExpanded(e);
            GetSubItems();
        }


        public static TfsItem CreateTfsItem(VersionControlServer vcs, string path)
        {
            var item = vcs.GetItem(path);
            return CreateTfsItem(vcs, item, true);
        }

        public static TfsItem CreateTfsItem(VersionControlServer vcs, Item item, bool canBeChecked)
        {
            TfsItem tfsItem = null;
            switch (item.ItemType)
            {
                case ItemType.File:
                    tfsItem = new TfsItem
                    {
                        IsFolder = false,
                        ItemName = item.ServerItem.Substring(item.ServerItem.LastIndexOf('/') + 1),
                        FullPath = item.ServerItem,
                        versionControlServer = vcs
                    };
                    break;
                case ItemType.Folder:
                    tfsItem = new TfsItem
                    {
                        IsFolder = true,
                        ItemName = item.ServerItem.Substring(item.ServerItem.LastIndexOf('/') + 1),
                        FullPath = item.ServerItem,
                        versionControlServer = vcs
                    };
                    tfsItem.Items.Add(tfsItem.CreateWorking());
                    break;
            }

            tfsItem.checkBox = new CheckBox {Content = new TextBlock {Text = tfsItem.ItemName}, Tag = tfsItem};
            tfsItem.checkBox.Checked += checkBox_Checked;
            tfsItem.checkBox.Unchecked += checkBox_Unchecked;
            tfsItem.Header = tfsItem.checkBox;
            tfsItem.CanBeChecked = canBeChecked;
            return tfsItem;
        }

        public static void SetCanBeCheckedTrue(TfsItem tfsItem)
        {
            tfsItem.CanBeChecked = true;
        }

        public static void SetCanBeCheckedFalse(TfsItem tfsItem)
        {
            tfsItem.CanBeChecked = false;
        }

        private static void checkBox_Unchecked(object sender, RoutedEventArgs e)
        {
            SetCheckedStateForItem(sender);
        }

        private static void checkBox_Checked(object sender, RoutedEventArgs e)
        {
            SetCheckedStateForItem(sender);
        }

        private static void SetCheckedStateForItem(object sender)
        {
            var checkBox = sender as CheckBox;
            if (checkBox == null) return;
            if (checkBox.IsEnabled)
            {
                var tfsItem = checkBox.Tag as TfsItem;
                if (tfsItem == null) return;
                tfsItem.CheckCheck(checkBox.IsChecked ?? false);
            }
        }

        private void CheckCheck(bool newState)
        {
            var tvie = new TreeViewItemsEnumerable(this);
            var itemsToUncheck = new List<TreeViewItem>();
            foreach (var tvi in tvie)
            {
                var tfsItem = tvi as TfsItem;

                if ((tfsItem != null) && (tfsItem != this))
                {
                    if (tfsItem.Checked)
                    {
                        itemsToUncheck.Add(tfsItem);
                    }
                }
            }

            if ((itemsToUncheck.Count == 0) ||
                (MessageBox.Show("Some child item is checked. Uncheck?", "TFS items", MessageBoxButton.OKCancel) ==
                 MessageBoxResult.OK))
            {
                Checked = newState;
                foreach (var tvi in tvie)
                {
                    var tfsItem = tvi as TfsItem;
                    if (tfsItem != this)
                    {
                        var isCanBeChecked = !(Checked);
                        if (isCanBeChecked)
                        {
                            SetCanBeCheckedTrue(tfsItem);
                        }
                        else
                        {
                            SetCanBeCheckedFalse(tfsItem);
                        }
                        tfsItem.Checked = false;
                    }
                }
            }
            else
            {
                checkBox.IsChecked = Checked;
            }
        }

        private TfsItem CreateWorking()
        {
            working = new TfsItem {Header = "Working..."};
            return working;
        }

        public override string ToString()
        {
            return FullPath;
        }

        internal TfsItem FindSubItem(string itemName)
        {
            if (Items != null)
            {
                foreach (var item in Items)
                {
                    var tfsItem = item as TfsItem;
                    if (tfsItem.ItemName == itemName)
                    {
                        return tfsItem;
                    }
                }
                return null;
            }
            return null;
        }
    }
}